//===============================================================================
// Microsoft patterns & practices
// Guidance Explorer Offline Client
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using GuidanceExplorer.Services;

namespace GuidanceExplorer.Model
{
    /// <summary>
    /// Represents a type of guidance.
    /// </summary>
    public class GuidanceType : GuidanceItemFileReference
    {
        #region Public Constants

        /// <summary>
        /// The name of the reference guidance type.
        /// </summary>
        public const string ReferenceTypeName = "reference";

        /// <summary>
        /// The name of the template guidance type.
        /// </summary>
        public const string TemplateTypeName = "template";

        /// <summary>
        /// The default guidance type name for column configuration of elements whose type can't be inferred.
        /// </summary>
        public const string DefaultTypeName = "guideline";

        public const string ChecklistTypeName = "checklist";
        #endregion

        #region Static members

        /// <summary>
        /// The static list of all guidance types.
        /// </summary>
        private static Dictionary<string, GuidanceType> _instances = new Dictionary<string, GuidanceType>(StringComparer.InvariantCultureIgnoreCase);

        /// <summary>
        /// Return the list of Guidance types.
        /// </summary>
        public static List<GuidanceType> AllGuidanceTypes
        {
            get
            {
                List<GuidanceType> allTypes = new List<GuidanceType>();
                foreach (GuidanceType type in _instances.Values)
                {
                    allTypes.Add(type);
                }
                return allTypes;
            }
        }

        /// <summary>
        /// Factory.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static GuidanceType New(string name)
        {
            if (_instances.ContainsKey(name))
            {
                return _instances[name];
            }
            GuidanceType guidanceType = new GuidanceType();
            guidanceType.Name = name;
            _instances[name] = guidanceType;
            return guidanceType;
        }

        /// <summary>
        /// Returns an instance of a GuidanceType
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static GuidanceType Get(string name)
        {
            if (_instances.ContainsKey(name))
            {
                return _instances[name];
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Returns an instance of a GuidanceType
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static GuidanceType GetById(string Id)
        {
            foreach (GuidanceType gType in _instances.Values)
            {
                if (gType.Id == Id)
                {
                    return gType;
                }
            }

            return null;
        }

        /// <summary>
        /// Adds an existing GuidanceType to the instance
        /// </summary>
        /// <remarks>If there's a GuidanceType with the same it, it's overriden</remarks>
        /// <param name="type"></param>
        public static void AddGuidanceType(GuidanceType type)
        {
            _instances[type.Name] = type;
        }

        /// <summary>
        /// Remove the GuidanceType from the list.
        /// </summary>
        /// <param name="name">The guidance type name.</param>
        public static bool RemoveGuidanceType(string name)
        {
            return _instances.Remove(name);
        }

        /// <summary>
        /// Remove the GuidanceType from the list.
        /// </summary>
        /// <param name="name">The guidance type name.</param>
        public static bool RemoveGuidanceTypeById(string Id)
        {
            GuidanceType gType = GetById(Id);

            return _instances.Remove(gType.Name);
        }

        #endregion

        #region Private members

        /// <summary>
        /// The name of the gudance type.
        /// </summary>
        private string _name;

        /// <summary>
        /// The schema id of the gudance type.
        /// </summary>
        private string _schemaId;

        /// <summary>
        /// The display name of the gudance type.
        /// </summary>
        private string _displayName;

        /// <summary>
        /// The display name of the gudance type when it's being used in lists.
        /// </summary>
        private string _listDisplayName;

        /// <summary>
        /// The display name of the gudance type when it's being used in the context if a new item.
        /// </summary>
        private string _newGuidanceTypeDisplayName;

        /// <summary>
        /// The file name for the template.
        /// </summary>
        private string _templateFileName;

        /// <summary>
        /// The file name for the missing file text.
        /// </summary>
        private string _missingFileName;

        /// <summary>
        /// The file name for the schema.
        /// </summary>
        private string _schemaFileName;

        /// <summary>
        /// The file name for the example.
        /// </summary>
        private string _exampleFileName;

        /// <summary>
        /// Whether the GuidanceType has been deleted. Used to preserve GuidanceType's items 
        /// </summary>
        private bool _isDeleted = false;

        /// <summary>
        /// The file name to the image for the node.
        /// </summary>
        private string _imageFileName;

        /// <summary>
        /// The image for the treeNodes for this guidance type.
        /// </summary>
        private Image _image;

        /// <summary>
        /// The list of the fields for the guidance type.
        /// </summary>
        private FieldCollection _fields = new FieldCollection();

        /// <summary>
        /// The name of the guidancetype node.
        /// </summary>
        private string _nodeDisplayName;

        #endregion

        #region Constructor

        /// <summary>
        /// Default constructor.
        /// </summary>
        private GuidanceType()
        {
            this.Title = String.Empty;
        }

        #endregion

        #region Public properties

        /// <summary>
        /// The schema id of the guidance type.
        /// </summary>
        [Browsable(false)]
        public string SchemaId
        {
            get { return _schemaId; }
            set { _schemaId = value; }
        }

        /// <summary>
        /// The name of the gudance type.
        /// </summary>
        [Browsable(true)]
        [ReadOnly(true)]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        /// <summary>
        /// The image for the treeNodes for this guidance type.
        /// </summary>
        [Browsable(false)]
        public Image Image
        {
            get { return _image; }
            set { _image = value; }
        }

        /// <summary>
        /// The display name of the gudance type.
        /// </summary>
        [Browsable(true)]
        [ReadOnly(true)]
        public string DisplayName
        {
            get { return _displayName; }
            set { _displayName = value; }
        }

        /// <summary>
        /// The display name of the gudance type when it's being used in lists.
        /// </summary>
        [Browsable(false)]
        public string ListDisplayName
        {
            get { return _listDisplayName; }
            set { _listDisplayName = value; }
        }

        /// <summary>
        /// Returns a Collection with the Fields of all the current GuidanceTypes
        /// </summary>
        /// <returns></returns>
        public static FieldCollection GetAllFields()
        {
            FieldCollection fields = new FieldCollection();
            foreach (GuidanceType type in AllGuidanceTypes)
            {
                foreach (Field f in type.Fields.Values)
                {
                    if (!fields.ContainsKey(f.Name))
                    {
                        fields.Add(f.Name, f.Clone());
                    }
                }
            }

            return fields;
        }

        /// <summary>
        /// The display name of the gudance type when it's being used in the context if a new item.
        /// </summary>
        [Browsable(false)]
        public string NewGuidanceTypeDisplayName
        {
            get { return _newGuidanceTypeDisplayName; }
            set { _newGuidanceTypeDisplayName = value; }
        }

        /// <summary>
        /// The name of the guidancetype node.
        /// </summary>
        [Browsable(false)]
        public string NodeDisplayName
        {
            get { return _nodeDisplayName; }
            set { _nodeDisplayName = value; }
        }

        /// <summary>
        /// The file name for the schema.
        /// </summary>
        [Browsable(false)]
        public string SchemaFileName
        {
            get { return _schemaFileName; }
        }

        /// <summary>
        /// The file path for the schema.
        /// </summary>
        [Browsable(false)]
        public string SchemaFilePath
        {
            get { return Path.GetFullPath(Path.Combine(ModelStorageService.TemplateFolder, SchemaFileName)); }
        }

        /// <summary>
        /// The file name for the missing file text.
        /// </summary>
        [Browsable(false)]
        public string MissingFileName
        {
            get { return "MissingFile.xml"; }
        }

        /// <summary>
        /// The file name for the template.
        /// </summary>
        [Browsable(false)]
        public string TemplateFileName
        {
            get { return _templateFileName; }
            set 
            { 
                _templateFileName = value;
                //schema is templateFileName.schema.xml
                _schemaFileName = Path.GetFileNameWithoutExtension(_templateFileName) + ".schema" + Path.GetExtension(_templateFileName);
            }
        }

        /// <summary>
        /// The file path for the template.
        /// </summary>
        [Browsable(false)]
        public string TemplateFilePath
        {
            get { return Path.GetFullPath(Path.Combine(ModelStorageService.TemplateFolder, TemplateFileName)); }
        }

        /// <summary>
        /// Whether the GuidanceType has been deleted. Used to preserve GuidanceType's items 
        /// </summary>
        [Browsable(false)]
        public bool IsDeleted
        {
            get { return _isDeleted; }
            set { _isDeleted = value; }
        }

        /// <summary>
        /// The file name to the image for the node.
        /// </summary>
        [Browsable(false)]
        public string ImageFileName
        {
            get { return _imageFileName; }
            set { _imageFileName = value; }
        }

        /// <summary>
        /// The file name for the example.
        /// </summary>
        [Browsable(false)]
        public string ExampleFileName
        {
            get { return _exampleFileName; }
            set { _exampleFileName = value; }
        }

        /// <summary>
        /// The file path for the example.
        /// </summary>
        [Browsable(false)]
        public string ExampleFilePath
        {
            get { return Path.GetFullPath(Path.Combine(ModelStorageService.TemplateFolder, _exampleFileName)); }
        }

        /// <summary>
        /// The list of the fields for the guidance type.
        /// </summary>
        [Browsable(false)]
        public FieldCollection Fields
        {
            get { return _fields; }
            set { _fields = value; }
        }

        #endregion

        /// <summary>
        /// Returns a clone instance of the current GuidanceType
        /// </summary>
        /// <returns></returns>
        public new GuidanceType Clone()
        {
            GuidanceType newType = new GuidanceType();
            newType.Id = this.Id;
            newType.FileName = this.FileName;
            newType.DisplayName = this.DisplayName;
            newType.ExampleFileName = this.ExampleFileName;
            newType.ImageFileName = this.ImageFileName;
            newType.ListDisplayName = this.ListDisplayName;
            newType.Name = this.Name;
            newType.NewGuidanceTypeDisplayName = this.NewGuidanceTypeDisplayName;
            newType.TemplateFileName = this.TemplateFileName;
            newType.NodeDisplayName = this.NodeDisplayName;

            foreach (Field f in this.Fields.Values)
            {
                Field newField = f.Clone();
                newType.Fields.Add(newField.Name, newField);
            }

            return newType;
        }
    }
}

